<?php
namespace App\Http\Middleware;

use App\Exception\OverfrequencyException;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Console\Router\Module;
use Swoft\Http\Message\Request;
use Swoft\Http\Message\Response;
use Swoft\Http\Server\Contract\MiddlewareInterface;
use Swoft\Redis\Redis;
use App\Http\Validator\TraceValidator;

/**
 * 超频检测
 * Class OverfrequencyMiddleware
 * @package App\Http\Middleware
 * @Bean("OverfrequencyMiddleware")
 */
class OverfrequencyMiddleware implements MiddlewareInterface
{

    /**
     * 唯一ID 存活时间
     * @var int
     */
    private $ttl = 5;

    /**
     * @param ServerRequestInterface $request
     * @param RequestHandlerInterface $handler
     * @return ResponseInterface
     * @throws OverfrequencyException
     * @throws \Swoft\Validator\Exception\ValidatorException
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // 检测超频设置
        if (!constant(Module::DEFINE_DISABLE_OVERFREQUENCY)) {
            // 开启了超频检测
            // 获取所有类型的数据
            $requestData = $request->input();
            if (! isset($requestData['trace_id'])) {
                throw new OverfrequencyException();
            }
            // 唯一凭证检测
            validate($requestData, "TraceValidator", ['trace_id']);

            $key = 'trace_id:'.$requestData['trace_id'];
            // 获取一下key是否存在
            $exists = Redis::exists($key);
            // 不管超不超频 都更新当前 trace_id 到redis 中 防止不良用户  写成了死循环 读取或插入数据
            Redis::setex($key, $this->ttl, 0);
            if ($exists) {
                // 超频了
                throw new OverfrequencyException();
            }
        }
        return $handler->handle($request);
    }
}
